extends Node
class_name GlobalUtil

static func create_texture_from_absolute_path(path:String):
	return ImageTexture.create_from_image(Image.load_from_file(path))

static func copy_img_to_user_dir(img_path):
	return copy_file_to_dir(img_path, GlobalVariables.img_dir).replace(OS.get_user_data_dir(),'user:/')

static func copy_file_to_dir(from:String, to_dir:String):
	if not from.is_absolute_path():
		from = ProjectSettings.globalize_path(from)
	
	if not to_dir.is_absolute_path():
		to_dir = ProjectSettings.globalize_path(to_dir)
	
	if not DirAccess.dir_exists_absolute(to_dir):
		DirAccess.make_dir_absolute(to_dir)
	
	var to_target = to_dir+from.get_file()
	DirAccess.copy_absolute(from, to_target)
	return to_target

static func get_task_todays_delayed_schedules_number(taskID:String)->int:
	var today_str = GlobalVariables.format_date(GlobalVariables.get_current_date())
	var number = 0
	for schedule_id in GlobalVariables.schedule_config_file.get_section_keys('schedule'):
		var scheduleData = GlobalVariables.get_schedule_data(schedule_id)
		if scheduleData.related_task == taskID and scheduleData.schedule_date==today_str:
			var state = GlobalVariables.check_schedule_state(scheduleData)
			if state == GlobalVariables.ScheduleState.DELAYED or  state == GlobalVariables.ScheduleState.FINISHED:
				number +=1
	return number

static func arrange_task_schedules(taskEn:TaskEntity):
	# 首先获得当前的单次工作时间，以及每天的工作次数
	var epoch_length = GlobalVariables.epoch_lengths[taskEn.single_epoch_length]
	var epoch_num = taskEn.epoch_num
	# 获得每周工作时间
	var working_days = taskEn.working_days
	var working_periods = taskEn.prefered_periods
	
	# 第一件事情，检查当前任务进度是否符合预期, 是否已经完成
	if not check_task_process(taskEn):
		# 如果不符合预期，重新计算epoch_num，一天工作多少节
		epoch_num = recal_epoch_num(taskEn)
		
		if not check_working_time_space(epoch_num, epoch_length,taskEn):
			return null
	
	GlobalVariables.del_task_schedules(taskEn.tid)
	
	# 获得今天的日期
	var today = GlobalVariables.get_current_date()
	var start_date = GlobalVariables.time_str_2_date(taskEn.start_time)
	if  start_date.is_before(today):
		start_date = today
		
	# TODO 是否从今天开始规划，如果不是就是从明天开始
	if not GlobalVariables.settingData.doScheduleFromToday:
		start_date.add_days(1)
	
	#遍历子任务
	var subtasks = taskEn.subtasks
	var epoch_added_today:int = 0
	if GlobalVariables.settingData.doScheduleFromToday:
		epoch_added_today = get_task_todays_delayed_schedules_number(taskEn.tid)
	
	var subtask_results = []
	for task_no in range(subtasks.size()):
		var subtask = subtasks[task_no]
		var results = GlobalVariables.assign_schedule_by_subtask(subtask,start_date.duplicate(),\
			working_periods, epoch_length, epoch_num, \
			taskEn.tid, task_no, working_days,epoch_added_today)
		
		var schedule_ids = results[0]
		start_date = results[1]
		epoch_added_today = results[2]
		
		subtask_results.append(schedule_ids)
	
	Signalbus.schedules_arranged.emit()
	return subtask_results
		
# 检查任务进度
static func check_task_process(taskEn:TaskEntity)->bool:
	
	var in_planed = true
	# 首先去获得今天之前的子任务
	for subtask in taskEn.subtasks:
		# 获得subtask关联的schedules
		#var schedule_ids = subtask.related_schedules
		#var subtask_hours_used  = 0
		#for schedule_id in schedule_ids:
			#var scheduleData = GlobalVariables.get_schedule_data(schedule_id)
			#if scheduleData == null:
				#continue
			#var state = GlobalVariables.check_schedule_state(scheduleData)
			##if state == GlobalVariables.ScheduleState.UNFINISHED or state == GlobalVariables.ScheduleState.DELAYED:
				###这两种表示没有完成
				##pass
			##
			#if state == GlobalVariables.ScheduleState.FINISHED:
				## 表示已经完成
				#subtask_hours_used += ceili(taskEn.single_epoch_length/float(60))
		#subtask.subtask_hours_used = subtask_hours_used
		if subtask.subtask_hours > subtask.subtask_hours_used:
			in_planed = false
	
	return in_planed

# 重新计算epoch_num
static func recal_epoch_num(taskEn:TaskEntity)->int:
	var hours_last = taskEn.working_hours - taskEn.hours_used
	var days_last = cal_task_end_length(taskEn)
	var epoch_length = GlobalVariables.epoch_lengths[taskEn.single_epoch_length]/float(60)
	return ceili(hours_last/days_last/epoch_length)

static func cal_task_end_length(taskEn:TaskEntity)->int:
	var startDate = GlobalVariables.time_str_2_date(taskEn.start_time)
	var endDate = GlobalVariables.time_str_2_date(taskEn.end_time)
	
	if taskEn.working_days == null or taskEn.working_days.size()==0:
		return endDate.days_to(startDate)+1
	
	var today = GlobalVariables.get_current_date()
	if startDate.is_before(today):
		startDate = today
	
	#计算需要能够工作多少天
	var day_num = 0
	while not startDate.is_after(endDate):
	# 需要根据 working days重新计算可以工作多少天
		if startDate.duplicate().get_weekday_iso() in taskEn.working_days:
			day_num += 1
		startDate.add_days(1)
	return day_num

#检查选择的工作偏好时间是否满足需求
static func check_working_time_space(epoch_num:int,epoch_length:int,taskEn:TaskEntity)->bool:
	var time_zone_length = 0
	for zone in taskEn.prefered_periods:
		time_zone_length += GlobalVariables.period_time_zone_length[zone]
	if epoch_num*epoch_length > time_zone_length:
		return true
	return true

# 检查任务的剩余时间
static func get_task_last_day_num(taskEn:TaskEntity)->int:
	if GlobalVariables.settingData.doScheduleFromToday:
		return GlobalVariables.time_str_2_date(taskEn.end_time).days_to(GlobalVariables.get_current_date())+1
	else:
		return GlobalVariables.time_str_2_date(taskEn.end_time).days_to(GlobalVariables.get_current_date())

# 遍历abilityEn去统计子类所有的hours
static func stat_ability_hours(abilityEn:AbilityEntity)->float:
	var hour:float = abilityEn.hours
	if abilityEn.children_id.size()>0:
		for child_id in abilityEn.children_id:
			var child_ability = GlobalVariables.get_ability(child_id)
			hour+=stat_ability_hours(child_ability)
		return hour
	else:
		return hour

#只运行一次，更新时间
static func update_ability_hours_by_tasks():
	# TODO 规划任务时似乎出现问题
	for schedule_id in GlobalVariables.schedule_config_file.get_section_keys('schedule'):
		var schedule = GlobalVariables.get_schedule_data(schedule_id)
		var task = GlobalVariables.load_task(schedule.related_task)
		var related_ability = GlobalVariables.get_ability(task.related_ability)
		related_ability.hours += float(schedule.actual_length)/3600
		GlobalVariables.save_ability_directly(related_ability)

static func remove_node_children(node:Node,excepts=[]):
	for child in node.get_children():
		if child not in excepts:
			node.remove_child(child)

static func send_notification(msg:String):
	Signalbus.notification_send.emit(msg)

static func sort_task(taskA:TaskEntity, taskB:TaskEntity)->bool:
	
	if taskA.isFinished:
		return false
	else:
		if taskB.isFinished:
			return true
		else:
			return GlobalUtil.get_task_last_day_num(taskA) < GlobalUtil.get_task_last_day_num(taskB)

### resolutions
static func set_resolution(resolution:String):
	var rels = resolution.split('*')
	var resolution_vector = Vector2i(int(rels[0]),int(rels[1]))
	DisplayServer.window_set_size(resolution_vector)
	var screen_size = DisplayServer.screen_get_size()
	var pos = (screen_size-resolution_vector)/2
	if pos.x <=0:
		pos.x = 50
	if pos.y <0:
		pos.y = 50
	DisplayServer.window_set_position(pos)
